package com.duobaoyu.dby.supply.message.listener.hander.refund;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.duobaoyu.dby.channel.adapter.enums.biz.refund.AfterSaleStatusEnum;
import com.duobaoyu.dby.channel.adapter.util.ChannelCodeUtils;
import com.duobaoyu.dby.channel.boundary.bean.refund.result.AfterSaleReturnAddressResult;
import com.duobaoyu.dby.common.mybatis.util.EnumUtils;
import com.duobaoyu.dby.supply.biz.client.boundary.refund.AfterSaleBoundaryClient;
import com.duobaoyu.dby.supply.biz.constant.OperateSourceConstants;
import com.duobaoyu.dby.supply.biz.producer.constant.SupplyChainMQConstants;
import com.duobaoyu.dby.supply.biz.service.order.OrderService;
import com.duobaoyu.dby.supply.biz.service.refund.AfterSaleService;
import com.duobaoyu.dby.supply.biz.service.refund.AfterSaleStateMachine;
import com.duobaoyu.dby.supply.biz.service.refund.event.AfterSaleStateChangeEvent;
import com.duobaoyu.dby.supply.common.biz.bo.refund.*;
import com.duobaoyu.dby.supply.common.biz.bo.refund.client.AfterSaleApplyClientOutBO;
import com.duobaoyu.dby.supply.core.dinger.annotation.DingerTalk;
import com.duobaoyu.dby.supply.core.rocketmq.handler.AbstractClusterMessageHandler;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.stereotype.Component;

import java.util.List;


/**
 *
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AfterSaleStatusChangeMessageHandler extends AbstractClusterMessageHandler<AfterSaleStateChangeEvent> {

    private final OrderService orderService;

    private final AfterSaleService afterSaleService;

    private final AfterSaleBoundaryClient afterSaleBoundaryClient;

    private final AfterSaleStateMachine afterSaleStateMachine;

    @Override
    public String getTopic() {
        return SupplyChainMQConstants.SupplyChainTopic.AFTER_SALE_TOPIC;
    }

    @Override
    public String getTag() {
        return SupplyChainMQConstants.SupplyChainTopic.AfterSaleTag.AFTER_SALES_STATUS_CHANGE;
    }

    @Override
    @DingerTalk(title = "供应链售后状态变更消息Consumer")
    public boolean messageHandler(AfterSaleStateChangeEvent event, MessageExt messageExt) {
        try {
            createChannelAfterSale(event);
			channelAuditSuccess(event);
            noticeOrderAfterSaleStatusHasChange(event);
        } catch (Exception e) {
            log.warn("consume after sale status change message throw exception,msgId={},param={}", messageExt.getMsgId(), JSON.toJSONString(event));
            throw e;
        }
        return Boolean.TRUE;
    }

	private void channelAuditSuccess(AfterSaleStateChangeEvent event) {
		if (EnumUtils.eq(AfterSaleStatusEnum.CHANNEL_AUDIT_SUCCESS, event.getAfterSaleStatus())) {
			AfterSaleQuery query = new AfterSaleQuery();
			query.setAfterSaleSn(event.getAfterSaleSn());
			AfterSaleOutBO afterSale = afterSaleService.queryAfterSale(query);

			List<AfterSaleReturnAddressResult> addressResults = afterSaleBoundaryClient.afterSaleAddressQuery(Lists.newArrayList(afterSale));
			AfterSaleReturnAddressResult addressResult = CollUtil.getFirst(addressResults);
			AfterSaleCustomerReturnInfoInBO returnInfoInBO = new AfterSaleCustomerReturnInfoInBO();
			returnInfoInBO.setId(afterSale.getId());
			CustomerReturnAddressBO customerReturnAddressBO = new CustomerReturnAddressBO();
			customerReturnAddressBO.setAfterSaleSn(afterSale.getAfterSaleSn());
			customerReturnAddressBO.setChannelAfterServiceTel(addressResult.getChannelAfterServiceTel());
			customerReturnAddressBO.setChannelAfterServiceReceiver(addressResult.getChannelAfterServiceReceiver());
			customerReturnAddressBO.setChannelAfterServicePhone(addressResult.getChannelAfterServicePhone());
			customerReturnAddressBO.setChannelAfterServiceAddress(addressResult.getChannelAfterServiceAddress());
			returnInfoInBO.setCustomerReturnAddress(customerReturnAddressBO);
			afterSaleService.modifyCustomerReturnInfo(returnInfoInBO);
		}
	}

	private void createChannelAfterSale(AfterSaleStateChangeEvent event) {
        if (EnumUtils.eq(AfterSaleStatusEnum.TO_BE_SUBMITTED_FOR_CHANNEL, event.getAfterSaleStatus())) {
            AfterSaleQuery query = new AfterSaleQuery();
            query.setAfterSaleSn(event.getAfterSaleSn());
            AfterSaleOutBO afterSale = afterSaleService.queryAfterSale(query);
            AfterSaleStateContext context = new AfterSaleStateContext();
            if (event.getOrderAutoCancel()) {
                AfterSaleApplyClientOutBO result = afterSaleBoundaryClient.cancelOrder(afterSale);
                context.setAfterSale(afterSale);
                context.setCurrentAfterSaleStatus(calculateAfterSalesStatus(result.getApplyResult()));
                context.setChangeContentOperate(AfterSaleStateContext.ChangeContentOperate.builder()
                        .channelAfterSaleSn(result.getChannelAfterSaleSn())
                        .failReason(result.getErrorMessage()).build());
                context.setOperateSource(OperateSourceConstants.SYSTEM);
            } else {
                AfterSalePickUpBO pickUp = null;
                AfterSaleReturnShipmentBO returnShipment = null;
                if (ChannelCodeUtils.pickUpAddressAndReturnAddressNotNull(afterSale.getChannelCode())) {
                    pickUp = afterSaleService.queryPickUp(afterSale.getAfterSaleSn());
                    returnShipment = afterSaleService.queryReturnShipment(afterSale.getAfterSaleSn());
                }
                AfterSaleApplyClientOutBO result = afterSaleBoundaryClient.applyAfterSale(afterSale, pickUp, returnShipment);
                context.setAfterSale(afterSale);
                context.setCurrentAfterSaleStatus(calculateAfterSalesStatus(result.getApplyResult()));
                context.setChangeContentOperate(AfterSaleStateContext.ChangeContentOperate.builder()
                        .channelAfterSaleSn(result.getChannelAfterSaleSn())
                        .failReason(result.getErrorMessage()).build());
                context.setOperateSource(OperateSourceConstants.SYSTEM);
            }
            afterSaleStateMachine.exe(context);
        }
    }

    private Integer calculateAfterSalesStatus(Boolean applyResult) {
        return applyResult ? AfterSaleStatusEnum.TO_BE_REVIEWED_BY_CHANNEL.getValue() : AfterSaleStatusEnum.WAIT_REJECT_CONFIRM.getValue();
    }

    private void noticeOrderAfterSaleStatusHasChange(AfterSaleStateChangeEvent event) {
        if (EnumUtils.eq(AfterSaleStatusEnum.COMPLETED, event.getAfterSaleStatus())) {
            orderService.afterSaleCancelOrder(event.getOrderSn());
        }
        if (EnumUtils.eq(AfterSaleStatusEnum.FAIL, event.getAfterSaleStatus())) {
            orderService.syncChannelOrderInfo(event.getOrderSn());
        }
    }
}
